package com.zhanglinwei.openApiClient.wrapper;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Consumer;

public interface SQLWrapper<R, W extends SQLWrapper<R, W>> {

    W distinct(boolean condition);

    default W distinct() {
        return distinct(true);
    }

    default W select(R... columns) {
        return select(true, columns);
    }

    default W select(boolean condition, R... columns) {
        return select(condition, Arrays.asList(columns));
    }

    default W select(Collection<R> columns) {
        return select(true, columns);
    }

    W select(boolean condition, Collection<R> columns);

    default W selectCount(R column) {
        return selectCount(true, column, "");
    }

    default W selectCount(boolean condition, R column) {
        return selectCount(condition, column, "");
    }
    default W selectCount(R column, String alias) {
        return selectCount(true, column, alias);
    }

    W selectCount(boolean condition, R column, String alias);

    default W selectDistinctCount(R column) {
        return selectDistinctCount(true, column, "");
    }

    default W selectDistinctCount(boolean condition, R column) {
        return selectDistinctCount(condition, column, "");
    }

    default W selectDistinctCount(R column, String alias) {
        return selectDistinctCount(true, column, alias);
    }

    W selectDistinctCount(boolean condition, R column, String alias);

    default W selectSum(R column) {
        return selectDistinctCount(true, column, "");
    }

    default W selectSum(boolean condition, R column) {
        return selectSum(condition, column, "");
    }

    default W selectSum(R column, String alias) {
        return selectSum(true, column, alias);
    }

    W selectSum(boolean condition, R column, String alias);

    default W selectAvg(R column) {
        return selectAvg(true, column, "");
    }

    default W selectAvg(boolean condition, R column) {
        return selectAvg(condition, column, "");
    }

    default W selectAvg(R column, String alias) {
        return selectAvg(true, column, alias);
    }

    W selectAvg(boolean condition, R column, String alias);

    default W selectMin(R column) {
        return selectMin(true, column, "");
    }

    default W selectMin(boolean condition, R column) {
        return selectMin(condition, column, "");
    }

    default W selectMin(R column, String alias) {
        return selectMin(true, column, alias);
    }

    W selectMin(boolean condition, R column, String alias);

    default W selectMax(R column) {
        return selectMax(true, column, "");
    }

    default W selectMax(boolean condition, R column) {
        return selectMax(condition, column, "");
    }

    default W selectMax(R column, String alias) {
        return selectMax(true, column, alias);
    }

    W selectMax(boolean condition, R column, String alias);

    default W or() {
        return or(true);
    }

    W or(boolean condition);
    W or(boolean condition, Consumer<W> consumer);
    default W or(Consumer<W> consumer) {
        return or(true, consumer);
    }

    default W and() {
        return and(true);
    }
    W and(boolean condition);
    W and(boolean condition, Consumer<W> consumer);
    default W and(Consumer<W> consumer) {
        return and(true, consumer);
    }

    default W eq(R column, Object val) {
        return eq(true, column, val);
    }

    W eq(boolean condition, R column, Object val);

    default W ne(R column, Object val) {
        return ne(true, column, val);
    }

    W ne(boolean condition, R column, Object val);

    default W gt(R column, Object val) {
        return gt(true, column, val);
    }
    
    W gt(boolean condition, R column, Object val);
    
    default W ge(R column, Object val) {
        return ge(true, column, val);
    }
    
    W ge(boolean condition, R column, Object val);
    
    default W lt(R column, Object val) {
        return lt(true, column, val);
    }
    
    W lt(boolean condition, R column, Object val);
    
    default W le(R column, Object val) {
        return le(true, column, val);
    }
    
    W le(boolean condition, R column, Object val);

    default W between(R column, Object val1, Object val2) {
        return between(true, column, val1, val2);
    }
    
    W between(boolean condition, R column, Object val1, Object val2);
    
    default W notBetween(R column, Object val1, Object val2) {
        return notBetween(true, column, val1, val2);
    }
    
    W notBetween(boolean condition, R column, Object val1, Object val2);
    
    default W like(R column, Object val) {
        return like(true, column, val);
    }
    
    W like(boolean condition, R column, Object val);
    
    default W notLike(R column, Object val) {
        return notLike(true, column, val);
    }
    
    W notLike(boolean condition, R column, Object val);
    
    default W notLikeLeft(R column, Object val) {
        return notLikeLeft(true, column, val);
    }
    
    W notLikeLeft(boolean condition, R column, Object val);
    
    default W notLikeRight(R column, Object val) {
        return notLikeRight(true, column, val);
    }
    
    W notLikeRight(boolean condition, R column, Object val);
    
    default W likeLeft(R column, Object val) {
        return likeLeft(true, column, val);
    }
    
    W likeLeft(boolean condition, R column, Object val);
    
    default W likeRight(R column, Object val) {
        return likeRight(true, column, val);
    }
    
    W likeRight(boolean condition, R column, Object val);

    default W isNull(R column) {
        return isNull(true, column);
    }

    W isNull(boolean condition, R column);

    default W isNotNull(R column) {
        return isNotNull(true, column);
    }

    W isNotNull(boolean condition, R column);

    W in(boolean condition, R column, Collection<?> coll);

    default W in(R column, Collection<?> coll) {
        return in(true, column, coll);
    }

    default W in(R column, Object... values) {
        return in(true, column, values);
    }

    default W in(boolean condition, R column, Object... values) {
        return in(condition, column, values == null ? Collections.emptyList() : Arrays.asList(values));
    }

    W notIn(boolean condition, R column, Collection<?> coll);

    default W notIn(R column, Collection<?> coll) {
        return notIn(true, column, coll);
    }

    default W notIn(R column, Object... values) {
        return notIn(true, column, values);
    }

    default W notIn(boolean condition, R column, Object... values) {
        return notIn(condition, column, values == null ? Collections.emptyList() : Arrays.asList(values));
    }

    default W groupBy(boolean condition, R column) {
        return groupBy(condition, Collections.singletonList(column));
    }

    default W groupBy(R column) {
        return groupBy(true, column);
    }

    W groupBy(boolean condition, Collection<R> columns);

    default W groupBy(Collection<R> columns) {
        return groupBy(true, columns);
    }

    default W groupBy(R... columns) {
        return groupBy(true, columns);
    }

   default W groupBy(boolean condition, R... columns) {
       return groupBy(true, columns == null ? Collections.emptyList() : Arrays.asList(columns));
    }


    default W orderByAsc(boolean condition, R column) {
        return orderBy(condition, true, column);
    }

    default W orderByAsc(R column) {
        return orderByAsc(true, column);
    }

    default W orderByAsc(boolean condition, Collection<R> columns) {
        return orderBy(condition, true, columns);
    }

    default W orderByAsc(Collection<R> columns) {
        return orderByAsc(true, columns);
    }

    default W orderByAsc(R... columns) {
        return orderByAsc(true, columns);
    }

    default W orderByAsc(boolean condition, R... columns) {
        return orderByAsc(condition, columns == null ? Collections.emptyList() : Arrays.asList(columns));
    }

    default W orderByDesc(boolean condition, R column) {
        return orderBy(condition, false, column);
    }

    default W orderByDesc(R column) {
        return orderByDesc(true, column);
    }

    default W orderByDesc(Collection<R> columns) {
        return orderByDesc(true, columns);
    }

    default W orderByDesc(boolean condition, Collection<R> columns) {
        return orderBy(condition, false, columns);
    }

    default W orderByDesc(R... columns) {
        return orderByDesc(true, columns);
    }

    default W orderByDesc(boolean condition, R... columns) {
        return orderByDesc(condition, columns == null ? Collections.emptyList() : Arrays.asList(columns));
    }

    default W orderBy(boolean condition, boolean isAsc, R column) {
        return orderBy(condition, isAsc, Collections.singletonList(column));
    }

    W orderBy(boolean condition, boolean isAsc, Collection<R> columns);

    default W orderBy(boolean condition, boolean isAsc, R... columns) {
        return orderBy(condition, isAsc, columns == null ? Collections.emptyList() : Arrays.asList(columns));
    }

    default W having(Consumer<W> consumer) {
        return having(true, consumer);
    }

    W having(boolean condition, Consumer<W> consumer);

    default W limit(Number pageSize) {
        return limit(true, pageSize);
    }

    default W limit(boolean condition, Number pageSize) {
        return limit(condition, null, pageSize);
    }

    default W limit(Number pageNo, Number pageSize) {
        return limit(true, pageNo, pageSize);
    }

    W limit(boolean condition, Number pageNo, Number pageSize);

    String previewSql();

}
